package com.zbkj.crmeb.api.controller;

import static com.seatent.opensdk.util.HaidaiApiUtils.isBlank;
import static com.seatent.opensdk.util.HaidaiApiUtils.removeEnd;

import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.zbkj.crmeb.enums.OutOrderSourceEnum;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.constants.Constants;
import com.crmeb.core.common.CommonApiResult;
import com.crmeb.core.common.CommonResult;
import com.utils.ProductUtil;
import com.utils.SHA1Util;
import com.zbkj.crmeb.chant.model.ChannelMerchant;
import com.zbkj.crmeb.chant.service.IChannelMerchantService;
import com.zbkj.crmeb.order.request.OutOrderInfoRequest;
import com.zbkj.crmeb.order.request.OutOrderRequest;
import com.zbkj.crmeb.order.request.SeatentOrderItemRequest;
import com.zbkj.crmeb.order.request.SeatentPushOrderRequest;
import com.zbkj.crmeb.order.request.SeatentShipInfoRequest;
import com.zbkj.crmeb.order.response.SeatentResponse;
import com.zbkj.crmeb.payment.service.OrderPayService;
import com.zbkj.crmeb.payment.vo.wechat.CreateOrderResponseVo;
import com.zbkj.crmeb.store.model.StoreOrder;
import com.zbkj.crmeb.store.response.StoreOrderInfoResponse;
import com.zbkj.crmeb.store.service.StoreOrderService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
@RequestMapping("api/suyun/order")
@Api(tags = "外部订单创建")
public class ApiOrderController {
    @Autowired
    private StoreOrderService storeOrderService;
    @Autowired
    private IChannelMerchantService channelMerchantService;
    @Autowired
    private OrderPayService orderPayService;
    @Value("${seatent.appKey}")
    private String appKey;
    @Value("${seatent.secret}")
    private String secret;

    /**
     * 菜鸟物流回传
     * @author daigb
     * @date:  2023-01-05 15:16
     */
    @ApiOperation(value = "菜鸟物流回传")
    @RequestMapping(value = "/cainiao/confirm", method = RequestMethod.POST)
    public JSONObject cainiaoConfirm(@RequestBody String result, HttpServletRequest request){
        log.info("--------------- 收到菜鸟调用物流回传接口: {} ---------------", result);
        
        JSONObject json = new JSONObject();
        json.put("success", true);
        json.put("errorCode", 200);
        json.put("errorMsg", "");
        return json;
    }
    
    /**
     * 菜鸟订单状态回传
     * @author daigb
     * @date:  2023-01-05 15:16
     */
    @ApiOperation(value = "菜鸟物流回传")
    @RequestMapping(value = "/cainiao/sync", method = RequestMethod.POST)
    public JSONObject cainiaoSync(@RequestBody String result, HttpServletRequest request){
    	log.info("--------------- 收到菜鸟订单状态回传接口: {} ---------------", result);
    	
    	JSONObject json = new JSONObject();
    	json.put("success", true);
    	json.put("errorCode", 200);
    	json.put("errorMsg", "");
    	return json;
    }
    
    /**
     * 外部订单推送
     * @author
     * @since
     */
    @ApiOperation(value = "外部订单推送")
    @RequestMapping(value = "/push", method = RequestMethod.POST)
    public CommonApiResult<Object> push(@RequestBody OutOrderRequest outOrderRequest, HttpServletRequest request){
    	// 验签
    	String token = request.getHeader("token");
    	String millis = request.getHeader("millis");
    	String merNo = request.getHeader("merNo");
    	String merSecret = request.getHeader("merSecret");
    	log.info("--------------- token: {}, millis: {}, merNo: {}, merSecret: {}, 收到外部推送订单: {} ---------------", token, millis, merNo, merSecret, outOrderRequest);
    	if(!token.equals(ProductUtil.getSign(millis, merNo, merSecret))) {
    		return CommonApiResult.unauthorized("验签失败");
    	}
    	// 验证商户是否存在
    	ChannelMerchant channelMerchant = channelMerchantService.getOne(Wrappers.<ChannelMerchant>lambdaQuery()
    			.eq(ChannelMerchant :: getMerchantNo, merNo)
    			.eq(ChannelMerchant :: getMerchantSecret, merSecret)
    			.last("LIMIT 1")
    			);
    	if(null == channelMerchant) {
    		return CommonApiResult.unauthorized("商户不存在");
    	}
    	// 验证订单是否已存在
    	StoreOrder storeOrder = storeOrderService.getByOrderId("OT" + outOrderRequest.getOrderId());
    	if(null != storeOrder){
    		log.info("--------------- 推送外部订单已经存在,orderId:{} ---------------", storeOrder.getOrderId());
    		return CommonApiResult.failed("订单已经存在");
    	}
    	// 订单推送
    	boolean pushStatus = storeOrderService.pushOutOrder(outOrderRequest, channelMerchant);
    	
    	return pushStatus ? CommonApiResult.success() : CommonApiResult.failed();
    }
    
    /**
     * 生成微信支付二维码(不可用)
     * @author daigb
     * @date:  2022-12-05 10:19
     */
    @ApiOperation(value = "生成微信支付二维码")
    @RequestMapping(value = "/payOrder", method = RequestMethod.POST)
    public CommonResult<CreateOrderResponseVo> payOrder(@RequestBody OutOrderRequest outOrderRequest, HttpServletRequest request){
    	CreateOrderResponseVo vo = orderPayService.payOrder2(outOrderRequest.getOrderId(), outOrderRequest.getTotalPrice());
    	
    	return CommonResult.success(vo);
    }
    
    /**
     * 外部查询订单
     * @author
     * @since
     */
    @ApiOperation(value = "外部订单查询")
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public CommonApiResult<Object> find(@RequestParam(required = false) String orderId, @RequestParam(required = false) Integer status, HttpServletRequest request){
        // 验签
        String token = request.getHeader("token");
        String millis = request.getHeader("millis");
        String merNo = request.getHeader("merNo");
        String merSecret = request.getHeader("merSecret");
        log.info("--------------- 收到外部查询订单号: {}, 商户: {} ---------------", orderId, merNo);
        if(!token.equals(ProductUtil.getSign(millis, merNo, merSecret))) {
            return CommonApiResult.unauthorized("验签失败");
        }
        // 验证商户是否存在
        ChannelMerchant channelMerchant = channelMerchantService.getOne(Wrappers.<ChannelMerchant>lambdaQuery()
                .eq(ChannelMerchant :: getMerchantNo, merNo)
                .eq(ChannelMerchant :: getMerchantSecret, merSecret)
                .last("LIMIT 1")
                );
        if(null == channelMerchant) {
            return CommonApiResult.unauthorized("商户不存在");
        }
        
        // 查询订单详情并返回
        List<StoreOrder> storeOrders = storeOrderService.list(Wrappers.<StoreOrder>lambdaQuery()
                .eq(StoreOrder :: getMerId, channelMerchant.getId())
                .eq(!StringUtils.isEmpty(orderId), StoreOrder :: getOrderId, "OT" + orderId)
                .eq(null != status, StoreOrder :: getStatus, status)
                );
        List<StoreOrderInfoResponse> StoreOrderInfoResponses = new ArrayList<>();
        for(StoreOrder storeOrder : storeOrders) {
            StoreOrderInfoResponse storeOrderInfoResponse = storeOrderService.info(storeOrder.getId());
            storeOrderInfoResponse.setUser(null);
            storeOrderInfoResponse.setStatusStr(null);
            StoreOrderInfoResponses.add(storeOrderInfoResponse);
        }
        
        return CommonApiResult.success((long)StoreOrderInfoResponses.size(), StoreOrderInfoResponses);
    }
    
    @ApiOperation("海带云推单接口")
    @RequestMapping(value = "/seatent/push",method = RequestMethod.POST)
    public SeatentResponse HaidaiPush(@RequestBody String jsonParams, HttpServletRequest request) throws Exception {
        SeatentPushOrderRequest pushOrderRequest = JSONObject.toJavaObject(JSONObject.parseObject(jsonParams), SeatentPushOrderRequest.class);
        //加签使用
        Map<String, String> map = JSONObject.toJavaObject(JSONObject.parseObject(jsonParams), Map.class);
        String orderSn = pushOrderRequest.getOrderSn();
        log.info("---------------收到外部海带云推单: {}, 电商平台备案名称: {}  ---------------", orderSn, pushOrderRequest.getCommercePlatformRecordName());
        SeatentResponse result = new SeatentResponse();
        result.setCode("400");
        result.setResult(0);
        result.setSuccess(false);
        // 验签
        if(!checkedSeatentSign(map, request)) {
            log.info("--------------- 外部海带云推单失败: topSign不正确 ---------------");
            result.setMessage("推单失败: topSign不正确");
            
            return result;
        }
        // 验证订单是否已存在
        StoreOrder storeOrder = storeOrderService.getByOrderId("OT" + orderSn);
        if(null != storeOrder){
            log.info("--------------- 外部海带云推单订单已经存在, orderId:{} ---------------", storeOrder.getOrderId());
            result.setMessage("订单已经存在");
            
            return result;
        }
        
        OutOrderRequest outOrderRequest = buildOutOrder(pushOrderRequest);
        // TODO 所属商户, 需要配置
        ChannelMerchant channelMerchant = channelMerchantService.getById(27);
        // 订单推送
        if(storeOrderService.pushOutOrder(outOrderRequest, channelMerchant)){
            result.setCode("200");
            result.setMessage("");
            result.setResult(1);
            result.setSuccess(true);
            Map<String, Object> orderId = new HashMap<>();
            orderId.put("depotOrderSn", "OT" + outOrderRequest.getOrderId());
            result.setData(orderId);
        }

        return result;
    }

    /**
     * 海带云订单验签
     * @author daigb
     * @date:  2022-11-07 14:29
     */
    private Boolean checkedSeatentSign(Map<String, String> parameterMap, HttpServletRequest request) throws Exception {
        //传过来的sign
        String topSign = parameterMap.get("topSign");

        for (Map.Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
            String name = entry.getKey();
            String[] values = entry.getValue();
            String value = "";
            for (String s : values) {
                value = s + ",";
            }
            value = value.substring(0, value.length() - 1);
            parameterMap.put(name, value);
        }
        parameterMap.remove("topSign");
        Map<String, String> sortedMap = SHA1Util.sortMap(parameterMap);
        StringBuilder sb = new StringBuilder();

        for (Map.Entry entry : sortedMap.entrySet()) {
            if (!isBlank((CharSequence) entry.getValue()) && !"secret".equals(entry.getKey())) {
                sb.append((String) entry.getKey());
                sb.append("=");
                sb.append(URLEncoder.encode((String) entry.getValue(), "UTF-8"));
                sb.append("&");
            }
        }

        //根据参数生成的sign
        String sign = SHA1Util.SHA1(secret + removeEnd(sb.toString(), "&") + secret).toUpperCase();

        //验证数据
        return sign.equals(topSign);
    }
    
    /**
     * 构建外部订单
     * @author daigb
     * @throws ParseException 
     * @date:  2022-11-07 14:36
     */
    private OutOrderRequest buildOutOrder(SeatentPushOrderRequest pushOrderRequest) throws ParseException {
    	// 收件信息
        SeatentShipInfoRequest shipInfoRequest = new SeatentShipInfoRequest();
        JSONObject shipInfoJson = JSONObject.parseObject(pushOrderRequest.getShipInfo());
        shipInfoRequest.setAddress(shipInfoJson.getString("address"))
                .setProvince(shipInfoJson.getString("province"))
                .setCity(shipInfoJson.getString("city"))
                .setRegion(shipInfoJson.getString("region"))
                .setIdentification(shipInfoJson.getString("identification"))
                .setName(shipInfoJson.getString("name"))
                .setPhone(shipInfoJson.getString("phone"))
                .setReceiverIdNum(shipInfoJson.getString("receiverIdNum"))
                .setReceiverName(shipInfoJson.getString("receiverName"));

        JSONArray itemJsonArray = JSONObject.parseArray(pushOrderRequest.getOrderItems());
        // 商品信息
        Map<String, SeatentOrderItemRequest> items = new HashMap<>();
        for (Object item : itemJsonArray){
            JSONObject jsonObject = (JSONObject) JSONObject.toJSON(item);
            SeatentOrderItemRequest itemRequest = new SeatentOrderItemRequest();
            itemRequest.setProductNum(jsonObject.getInteger("productNum"))
                    .setName(jsonObject.getString("name"))
                    .setNum(jsonObject.getInteger("num"))
                    .setPrice(jsonObject.getBigDecimal("price"))
                    .setSalePrice(jsonObject.getBigDecimal("salePrice"))
                    .setProductName(jsonObject.getString("productName"))
                    .setPsn(jsonObject.getString("psn"))
                    .setShippingAmount(jsonObject.getBigDecimal("shippingAmount"))
                    .setTax(jsonObject.getBigDecimal("tax"));
            items.put(jsonObject.getString("psn"), itemRequest);
        }
        // 创建订单信息
        OutOrderRequest outOrderRequest = new OutOrderRequest();
        outOrderRequest.setOrderId(pushOrderRequest.getOrderSn());
        // 姓名
        outOrderRequest.setRealName(shipInfoRequest.getReceiverName());
        // 身份证
        outOrderRequest.setIdCard(shipInfoRequest.getReceiverIdNum());
        outOrderRequest.setUserPhone(shipInfoRequest.getPhone());
        // 区域类型
        outOrderRequest.setUserAddress(shipInfoRequest.getAddress());
        outOrderRequest.setFreightPrice(pushOrderRequest.getShippingAmount());
        //订单商品总数
        int totalNum = 0;
        //订单总价
        BigDecimal totalPrice = BigDecimal.ZERO;
        for (String key : items.keySet()){
            totalNum += items.get(key).getNum();
            totalPrice = items.get(key).getPrice().multiply(BigDecimal.valueOf(items.get(key).getNum())).add(totalPrice);
        }
        outOrderRequest.setTotalNum(totalNum);
        outOrderRequest.setTotalPrice(totalPrice);
        outOrderRequest.setPayPrice(pushOrderRequest.getBuyAmount());
        outOrderRequest.setCreateTime(new SimpleDateFormat(Constants.DATE_FORMAT).parse(pushOrderRequest.getCreateTime()));
        outOrderRequest.setPayTime(new SimpleDateFormat(Constants.DATE_FORMAT).parse(pushOrderRequest.getPaySuccessTime()));
        outOrderRequest.setCreateName(shipInfoRequest.getReceiverName());
        outOrderRequest.setMark(pushOrderRequest.getRemark());
        outOrderRequest.setProvince(shipInfoRequest.getProvince());
        outOrderRequest.setCity(shipInfoRequest.getCity());
        outOrderRequest.setDistrict(shipInfoRequest.getRegion());
        outOrderRequest.setDetail(shipInfoRequest.getAddress().split("区")[shipInfoRequest.getAddress().split("区").length - 1]);
        outOrderRequest.setIsTof(true);
        outOrderRequest.setOutOrderSource(OutOrderSourceEnum.HAIDAI.getCode());
        List<OutOrderInfoRequest> outOrderInfoRequests = new ArrayList<>();
        for (String key : items.keySet()){
            SeatentOrderItemRequest itemRequest = items.get(key);
            OutOrderInfoRequest outOrderInfoRequest = new OutOrderInfoRequest();
            // TODO 目前固定商品
            outOrderInfoRequest.setBarCode("3000100002");
            outOrderInfoRequest.setSourceSkuId("553374");
            outOrderInfoRequest.setCartNum(itemRequest.getNum());
            outOrderInfoRequest.setPrice(totalPrice);
            OutOrderInfoRequest.Product product = new OutOrderInfoRequest.Product();
            OutOrderInfoRequest.Product.AttrInfo attrInfo = new OutOrderInfoRequest.Product.AttrInfo();
            attrInfo.setSuk(itemRequest.getProductNum().toString());
            attrInfo.setPrice(totalPrice);
            attrInfo.setCost(itemRequest.getPrice());
            attrInfo.setOtPrice(itemRequest.getSalePrice());
            attrInfo.setTaxPrice(itemRequest.getTax());
            attrInfo.setTaxAndSecondPrice(itemRequest.getShippingAmount().add(itemRequest.getTax()));
            product.setAttrInfo(attrInfo);
            outOrderInfoRequest.setProductInfo(product);
            outOrderInfoRequests.add(outOrderInfoRequest);
        }
        outOrderRequest.setOutOrderInfoRequest(outOrderInfoRequests);
        
    	return outOrderRequest;
    }
    
}
